package com.oe.rpc.context;

import com.alibaba.fastjson.JSONObject;
import com.oe.rpc.core.events.TryConnectEvent;
import com.oe.rpc.register.ServiceInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 服务列表对象
 */
public class ServiceList{


    private static Logger logger = LoggerFactory.getLogger(ServiceList.class);

    ExecutorService executorService =Executors.newFixedThreadPool(3);


    private  static ServiceList list = new ServiceList();

    final  String userHome = System.getProperty("user.home");

    final String dir="ldm-services";

    final String placeholder="XXX";

    final  String format=placeholder+".txt";

    ConcurrentHashMap<String,List<ServiceInfo>> serviceMap = new ConcurrentHashMap<>();

    ConcurrentHashMap<String,ServiceInfo>  indexTable= new ConcurrentHashMap<>();


    private ServiceList() {

    }

    public static ServiceList getList(){
        return list;
    }

    /**
     * 检查当前服务是否已经加载过
     * @param service
     */
    public boolean serviceHasLoad(String service){
       return serviceMap.get(service)!=null?true:false;
    }


    public  void updateLastInvokeTimes(String serviceId,long times){
        ServiceInfo info = indexTable.get(serviceId);
        info.setLessInvokeTimes(times);
    }


    /**
     * 更新某个服务下的机器列表
     * @param servicName
     * @param list
     */
    public  void updateServiceList(String servicName,List<ServiceInfo> list){
        synchronized (servicName.intern()){
            List<ServiceInfo> serviceInfos = serviceMap.get(servicName);
            if (serviceInfos==null||serviceInfos.size()==0){
                serviceMap.put(servicName,list);

                for (ServiceInfo serviceInfo : list) {
                 indexTable.put(serviceInfo.getServiceId(),serviceInfo);
                 logger.info("服务【{}】已上线！",serviceInfo.getServiceId());
                }
            }else {
                List<ServiceInfo> newArr=new ArrayList<>();
                Map<String,ServiceInfo> temp=new HashMap<>();
                for (ServiceInfo serviceInfo : list) {
                    temp.put(serviceInfo.getServiceId(),serviceInfo);
                    ServiceInfo exsistInfo = indexTable.get(serviceInfo.getServiceId());
                    if(exsistInfo==null){
                        newArr.add(serviceInfo);
                        indexTable.put(serviceInfo.getServiceId(),serviceInfo);
                        logger.info("服务【{}】已上线！",serviceInfo.getServiceId());
                    }else {
                        newArr.add(exsistInfo);

                    }
                }
                //刷新服务列表
                serviceMap.put(servicName,newArr);
                //找出差异项
                Iterator<ServiceInfo> iterator = serviceInfos.iterator();
                while (iterator.hasNext()){
                    ServiceInfo next = iterator.next();
                    ServiceInfo serviceInfo = temp.get(next.getServiceId());
                    if(serviceInfo!=null){
                        iterator.remove();
                    }
                }

                //删除索引
                for (ServiceInfo serviceInfo : serviceInfos) {
                    indexTable.remove(serviceInfo.getServiceId());
                    logger.info("服务【{}】已下线！",serviceInfo.getServiceId());
                }
            }


            //异步服务写进本地文件
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    String filePath=userHome+File.separator+dir+File.separator+format.replace(placeholder,servicName);
                    File file = new File(filePath);
                    try {
                        checkFile(file);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    try ( PrintWriter writer=new PrintWriter(new FileOutputStream(file));){
                        String serviceInfo=appendSeviceInfo(servicName,list);
                        writer.println(serviceInfo);
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            });

            /**
             * 异步尝试创建连接
             */
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    LdmRpcEventProcessor.newInstance().publish(new TryConnectEvent(list));
                }
            });

        }
    }


    private void checkFile(File file) throws Exception{
        // 检测目录建立目录
        if (!file.getParentFile().exists()) {
            boolean mkdirsflag = file.getParentFile().mkdirs();
            if (mkdirsflag != true) {
                throw new Exception("生成文件，本地创建目录失败!");
            }
        }
        // 检测文件建立文件
        if (!file.exists()) {
            boolean newFileFlag = file.createNewFile();
            if (newFileFlag != true) {
                throw new Exception("生成文件，本地创建文件失败!");
            }
        }
    }

    private String appendSeviceInfo(String servicName, List<ServiceInfo> list) {
        StringBuilder sb = new StringBuilder();
        sb.append(servicName).append("=").append(JSONObject.toJSONString(list));
        return sb.toString();
    }


    public  void loadSeiviceFromLocal(){
        List<File> allFile = getAllFile();
        if (allFile.size()>0){
            for (File file : allFile) {
                try ( BufferedReader reader = new BufferedReader(new FileReader(file))){
                    String line = reader.readLine();
                    if(line!=null&&line!=""){
                        String[] split = line.split("=");
                        List<ServiceInfo> serviceInfos = JSONObject.parseArray(split[1], ServiceInfo.class);
                        serviceMap.put(split[0],serviceInfos);
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }


            }
        }
    }

    private  List<File> getAllFile() {
        List<File> files = new ArrayList<>();
        File fileDir = new File(userHome+File.separator+dir);
        if(!fileDir.exists()){
            fileDir.mkdirs();
            return files;
        }
        String[] list = fileDir.list();
        if(list!=null&&list.length>0){
            for (String s : list) {
                String path=userHome+File.separator+dir+File.separator+s;
                        files.add(new File(path));
            }

        }
        return files;
    }

    @Override
    public String toString() {
        return "ServiceList{" +
                "userHome='" + userHome + '\'' +
                ", format='" + format + '\'' +
                ", serviceMap=" + serviceMap +
                '}';
    }

    public  List<ServiceInfo>  findServiesByName(String serviceName) {
        return  serviceMap.get(serviceName);
    }
}
